/**
* @file hal.h
* Hardware abstraction layer.
* It's a abstraction interface to control basic motherboard devices.
*
* Copyrights 2010 Michal Saman, m.saman@designplus.cz.
* This source code is release under the Apache License 2.0.
* http://www.apache.org/licenses/LICENSE-2.0
*/
#ifndef _HAL_H
#define _HAL_H

#ifndef ARCH_X86
#error "[hal.h] is platform-independent. Define ARCH_X86."
#endif

#include <stdint.h>

/**
 * Atomic variable structure
 */
typedef struct atomic {
	volatile int counter;
} atomic_t;

/**
 * Set atomic value i to atomic structure counter
 */
#define atomic_set(a, i)	(((a)->counter) = (i))

/*
 * Read atomic structure counter
 */
#define atomic_read(v)		((v)->counter)

/*
 * PIC base address to Interrupt Vector Table
 * Remember that the first 31 interrupts (0x0-0x1F) are reserved!
 * We map them to IRQs 32-47, right after these reserved interrupts.
 * First 8 IRQ's are handled by the primary PIC, so we map the primary PIC
 * to the base address of 0x20 (32 decimal), and the secondary PIC at 0x28 (40 decimal).
 * Remember there are 8 IRQ's for each PIC.
 */
#define	hal_pic_base0		0x20
#define	hal_pic_base1		0x28

extern int hal_init() __attribute__ ((cdecl));
extern int hal_shutdown() __attribute__ ((cdecl));

extern void generate_interrupt(int n) __attribute__ ((cdecl));
extern void	end_hw_interrupt(uint32_t n) __attribute__ ((cdecl));
extern void set_handler_interrupt(uint32_t n, void (*fn) () );

extern uint8_t inportb(uint16_t portid) __attribute__ ((cdecl));
extern void outportb(uint16_t portid, uint8_t value) __attribute__ ((cdecl));

extern uint16_t inportw(uint16_t portid) __attribute__ ((cdecl));
extern void outportw(uint16_t portid, uint16_t value) __attribute__ ((cdecl));

extern uint32_t inportdw(uint16_t portid) __attribute__ ((cdecl));
extern void outportdw(uint16_t portid, uint32_t value) __attribute__ ((cdecl));

extern void inportsw(uint16_t portid, void * buffer, size_t count) __attribute__ ((cdecl));
extern void outportsw(uint16_t portid, void * buffer, size_t count) __attribute__ ((cdecl));

/** INLINE FUNCTIONS **/

/**
* Function for enable HW interrupts (sti).
*/
static __inline__ void enable_interrupts() {
	__asm__ volatile ("sti");
}

/**
* Functin for disable all HW interrupts (cli)
*/
static __inline__ void disable_interrupts() {
	__asm__ volatile ("cli");
}

/**
 * Function performs atomic increment.
 */
static __inline__ void atomic_inc(atomic_t *a) {
	__asm__ volatile ("lock; incl %0" : "=m"(a->counter) : "m"(a->counter));
}

/**
 * Function performs atomic decrement.
 */
static __inline__ void atomic_dec(atomic_t *a) {
	__asm__ volatile ("lock; decl %0" : "=m"(a->counter) : "m"(a->counter));
}

#endif
